package org.javahispano.javacup.tacticas_aceptadas.aitkiar.es.ait.javacup;

import java.awt.Color;
import java.util.ArrayList;
import org.javahispano.javacup.modelo.*;
import java.util.List;

public class MarsupialesTarados implements Tactica
{

    Posicion balonAnterior = null;
    Posicion prediccionA20Turnos = null;
    int jugadoresNoSacan[] = { 0, 1, 2, 3, 10, 11 };

    // Cuando sacamos nosotros.
    Posicion alineacion1[] = new Posicion[]
    {
        new Posicion( 0.2595419847328244, -50.41044776119403 ),
        new Posicion( -19.46564885496183, -31.6044776119403 ),
        new Posicion( 0.2595419847328244, -31.082089552238806 ),
        new Posicion( 19.984732824427482, -31.6044776119403 ),
        new Posicion( 13.552447552447552, -18.529411764705884 ),
        new Posicion( -14.97902097902098, -15.203619909502263 ),
        new Posicion( -30.433566433566433, -2.1380090497737556 ),
        new Posicion( 29.95804195804196, -2.8506787330316743 ),
        new Posicion( -7.132867132867133, -2.3755656108597285 ),
        new Posicion( -2.6153846153846154, -12.352941176470589 ),
        new Posicion( 0.0, -2.1380090497737556 )
    };
    // Cuando sacan ellos
    Posicion alineacion2[] = new Posicion[]
    {
        new Posicion( 0.2595419847328244, -50.41044776119403 ),
        new Posicion( -26.391608391608393, -30.88235294117647 ),
        new Posicion( 0.2595419847328244, -31.082089552238806 ),
        new Posicion( 27.104895104895103, -28.50678733031674 ),
        new Posicion( 7.37062937062937, -19.004524886877828 ),
        new Posicion( -13.79020979020979, -19.95475113122172 ),
        new Posicion( -24.48951048951049, -14.015837104072398 ),
        new Posicion( 21.16083916083916, -11.877828054298643 ),
        new Posicion( -14.97902097902098, -3.3257918552036196 ),
        new Posicion( -2.6153846153846154, -12.352941176470589 ),
        new Posicion( 9.986013986013985, -7.839366515837104 )
    };

    // defendiendo
    Posicion alineacion3[] = new Posicion[]
    {
        new Posicion( 0.2595419847328244, -50.41044776119403 ),
        new Posicion( -19.020979020979023, -14.728506787330318 ),
        new Posicion( 0.4755244755244755, -14.490950226244346 ),
        new Posicion( 18.06993006993007, -14.96606334841629 ),
        new Posicion( 9.748251748251748, 4.98868778280543 ),
        new Posicion( -13.314685314685315, 6.651583710407239 ),
        new Posicion( -24.965034965034967, 20.192307692307693 ),
        new Posicion( 22.58741258741259, 19.004524886877828 ),
        new Posicion( -11.65034965034965, 36.58371040723982 ),
        new Posicion( -0.7132867132867133, 26.84389140271493 ),
        new Posicion( 8.797202797202797, 35.8710407239819 )
    };
    //Defendiendo
    Posicion alineacion4[] = new Posicion[]
    {
        new Posicion( 0.2595419847328244, -50.41044776119403 ),
        new Posicion( -25.916083916083913, -30.88235294117647 ),
        new Posicion( -1.4265734265734267, -36.34615384615385 ),
        new Posicion( 25.678321678321677, -30.88235294117647 ),
        new Posicion( 8.083916083916083, -27.556561085972852 ),
        new Posicion( -13.076923076923078, -28.031674208144796 ),
        new Posicion( -20.447552447552447, -14.25339366515837 ),
        new Posicion( 15.692307692307693, -14.015837104072398 ),
        new Posicion( -13.79020979020979, -4.751131221719457 ),
        new Posicion( -3.090909090909091, -15.678733031674208 ),
        new Posicion( 5.944055944055944, 13.540723981900454 )
    };

    class TacticaDetalleImpl implements TacticaDetalle
    {

        @Override
        public String getNombre()
        {
            return "Marsupiales Tarados";
        }

        @Override
        public String getPais()
        {
            return "Nunca Jamas";
        }

        @Override
        public String getEntrenador()
        {
            return "Aitkiar";
        }

        @Override
        public Color getColorCamiseta()
        {
            return new Color( 255, 255, 0 );
        }

        @Override
        public Color getColorPantalon()
        {
            return new Color( 255, 255, 0 );
        }

        @Override
        public Color getColorFranja()
        {
            return new Color( 255, 255, 51 );
        }

        @Override
        public Color getColorCalcetas()
        {
            return new Color( 255, 255, 51 );
        }

        @Override
        public Color getColorPortero()
        {
            return new Color( 255, 0, 0 );
        }

        @Override
        public EstiloUniforme getEstilo()
        {
            return EstiloUniforme.FRANJA_VERTICAL;
        }

        @Override
        public Color getColorCamiseta2()
        {
            return new Color( 101, 177, 138 );
        }

        @Override
        public Color getColorPantalon2()
        {
            return new Color( 0, 50, 52 );
        }

        @Override
        public Color getColorFranja2()
        {
            return new Color( 222, 0, 5 );
        }

        @Override
        public Color getColorCalcetas2()
        {
            return new Color( 134, 111, 23 );
        }

        @Override
        public Color getColorPortero2()
        {
            return new Color( 57, 44, 85 );
        }

        @Override
        public EstiloUniforme getEstilo2()
        {
            return EstiloUniforme.FRANJA_DIAGONAL;
        }

        class JugadorImpl implements JugadorDetalle
        {

            String nombre;
            int numero;
            Color piel, pelo;
            double velocidad, remate, presicion;
            boolean portero;
            Posicion posicion;

            public JugadorImpl( String nombre, int numero, Color piel, Color pelo,
                double velocidad, double remate, double presicion, boolean portero )
            {
                this.nombre = nombre;
                this.numero = numero;
                this.piel = piel;
                this.pelo = pelo;
                this.velocidad = velocidad;
                this.remate = remate;
                this.presicion = presicion;
                this.portero = portero;
            }

            @Override
            public String getNombre()
            {
                return nombre;
            }

            @Override
            public Color getColorPiel()
            {
                return piel;
            }

            @Override
            public Color getColorPelo()
            {
                return pelo;
            }

            @Override
            public int getNumero()
            {
                return numero;
            }

            @Override
            public boolean esPortero()
            {
                return portero;
            }

            @Override
            public double getVelocidad()
            {
                return velocidad;
            }

            @Override
            public double getRemate()
            {
                return remate;
            }

            @Override
            public double getPresicion()
            {
                return presicion;
            }
        }

        @Override
        public JugadorDetalle[] getJugadores()
        {
            return new JugadorDetalle[]
                {
                    //Portero
                    new JugadorImpl( "Jugador", 1, new Color( 255, 200, 150 ), new Color( 50, 0, 0 ), 1.0d, 1.0d, 0.5d, true ),
                    //Lateral Izquierdo
                    new JugadorImpl( "Jugador", 2, new Color( 255, 200, 150 ), new Color( 50, 0, 0 ), 1.0d, 0.75d, 0.5d, false ),
                    // Central
                    new JugadorImpl( "Jugador", 3, new Color( 255, 200, 150 ), new Color( 50, 0, 0 ), 1.0d, 0.75d, 0.5d, false ),
                    //Lateral Derecho
                    new JugadorImpl( "Jugador", 4, new Color( 255, 200, 150 ), new Color( 50, 0, 0 ), 1.0d, 0.75d, 0.5d, false ),
                    // Interior derecho
                    new JugadorImpl( "Jugador", 5, new Color( 255, 200, 150 ), new Color( 50, 0, 0 ), 1.0d, 0.87d, 0.5d, false ),
                    // Interior izquierdo
                    new JugadorImpl( "Jugador", 6, new Color( 255, 200, 150 ), new Color( 50, 0, 0 ), 1.0d, 0.87d, 0.5d, false ),
                    // Extremo izquierdo
                    new JugadorImpl( "Jugador", 7, new Color( 255, 200, 150 ), new Color( 50, 0, 0 ), 1.0d, 0.89d, 0.5d, false ),
                    // Extremo derecho
                    new JugadorImpl( "Jugador", 8, new Color( 255, 200, 150 ), new Color( 50, 0, 0 ), 1.0d, 0.88d, 0.5d, false ),
                    // Delantero izquierdo
                    new JugadorImpl( "Jugador", 9, new Color( 255, 200, 150 ), new Color( 50, 0, 0 ), 1.0d, 1.0d, 0.73d, false ),
                    // Enganche
                    new JugadorImpl( "Jugador", 10, new Color( 255, 200, 150 ), new Color( 50, 0, 0 ), 1.0d, 1.0d, 1.0d, false ),
                    // Delantero derecho
                    new JugadorImpl( "Jugador", 11, new Color( 255, 200, 150 ), new Color( 50, 0, 0 ), 1.0d, 1.0d, 1.0d, false )
                };
        }
    }
    TacticaDetalle detalle = new TacticaDetalleImpl();

    @Override
    public TacticaDetalle getDetalle()
    {
        return detalle;
    }

    @Override
    public Posicion[] getPosicionSaca( SituacionPartido sp )
    {
        return alineacion1;
    }

    @Override
    public Posicion[] getPosicionRecive( SituacionPartido sp )
    {
        return alineacion2;
    }

    @Override
    public List<Comando> ejecutar( SituacionPartido sp )
    {
        List comandos = new ArrayList<Comando>();
        Posicion balon;

        double velocidadBalon;
        double k;
        double y2;
        double x2;

        Posicion[] equipo = sp.misJugadores();
        Posicion[] rivales = sp.rivales();
        Posicion[] alineacion;

        balon = sp.balon();



        int rematar[] = sp.puedenRematar();

        if ( balonAnterior == null )
        {
            balonAnterior = balon;
        }

        // Prediccion de la siguiente posición del balón.
        velocidadBalon = balon.distancia( balonAnterior );
        if ( velocidadBalon > 0 )
        {
            k = velocidadBalon / ( 21 * velocidadBalon - 210 );
            y2 = ( balon.getY() * ( 1 + k ) - balonAnterior.getY() ) /  k;
            x2 = ( balon.getX() * ( 1 + k ) - balonAnterior.getX() ) /  k;
            prediccionA20Turnos = new Posicion( x2, y2 ).setDentroCampoJuego();
        }
        else
        {
            prediccionA20Turnos = null;
        }

        //Variables que nos indican el estado del partido
        boolean defendiendo = balon.getY() < 20 && ( balonAnterior.getY() > balon.getY() || balon.getY() < -30 );

        if ( defendiendo )
        {
            alineacion = alineacion4;
        }
        else
        {
            alineacion = alineacion3;
        }

        //------------ Control del portero.
        //
        // Calculamos la intersección entre la trayectoria del balón y la línea de meta e intentamos que el
        // portero se mueva siempre a ese punto. Si el balón está dentro del área pequeña va a por el. Siempre que tenga ocasión de
        // golpear hace un pase elevado en dirección al jugador más alejado de la portería.
        //
        Posicion intersec = Posicion.Interseccion( balonAnterior, balon, new Posicion( 9, -52.40 ), new Posicion( -9, -52.40 ) );
        if ( intersec != null && intersec.getX() >= Constantes.posteIzqArcoInf.getX() && intersec.getX() <= Constantes.posteDerArcoInf.getX() )
        {
            comandos.add( new ComandoIrA( 0, intersec ) );
        }
        else
        {
            comandos.add( new ComandoIrA( 0, alineacion[0]));
        }

        for ( int i = 0; i < rematar.length; i++ )
        {
            if ( rematar[i] == 0 )
            {
                comandos.add( new ComandoGolpearBalon( rematar[0], new Posicion( 0, 52.50 ), 1, true ) );
            }
        }


        //---------------- Control de los jugadores.
        //
        // Si es el jugador más cercano al balón va hacia el balón. Si no van a su posición de
        // ataque/defensa.
        //
        int jugadorMasCercano = balon.indiceMasCercano( equipo );
        int jugadorMasCercanoPrediccion;
        if ( prediccionA20Turnos != null )
        {
            jugadorMasCercanoPrediccion = prediccionA20Turnos.indiceMasCercano( equipo );
        }
        else
        {
            jugadorMasCercanoPrediccion = -1;
        }
        if ( sp.saco())
        {
            int jugadorSaque = balon.indiceMasCercano( equipo, jugadoresNoSacan );
            comandos.add( new ComandoIrA( jugadorMasCercano, balon ));
            for ( int i = 0; i < 11; i ++ )
            {
                if ( i != jugadorMasCercano )
                {
                    comandos.add( new ComandoIrA( i, alineacion[i]));
                }
            }
        }
        else
        {
            for ( int i = 1; i < 11; i++ )
            {
                if ( i == jugadorMasCercano )
                {
                    comandos.add( new ComandoIrA( i, balon ) );
                }
                else if ( i == jugadorMasCercanoPrediccion && !defendiendo)
                {
                    comandos.add( new ComandoIrA( i, prediccionA20Turnos));
                }
                else
                {
                    if ( defendiendo )
                    {
                        // comprobamos si hay jugadores que se situen cerca de las posiciones de defensa, y
                        // en caso afirmativo les marcamos.
                        int contrarioMasCercano = alineacion[i].indiceMasCercano( rivales );
                        if ( alineacion[i].distancia( rivales[contrarioMasCercano] ) < 30 && i != 9 && i != 7 && i != 6)
                        {
                            comandos.add( new ComandoIrA( i, rivales[contrarioMasCercano]));
                        }
                        else
                        {
                            comandos.add( new ComandoIrA( i, alineacion[i] ) );
                        }
                    }
                    else
                    {
                        comandos.add( new ComandoIrA( i, alineacion[i] ) );
                    }
                }
            }
        }

        // Si el jugador se encuentra lo bastante cerca de la portería tira a puerta, sino hace un
        // pase al jugador más cercano con mayor X. Si no se encuentra un jugador más cercano, avanza
        // con el balón
        boolean alto;
        for ( int i = 0; i < rematar.length; i++ )
        {
            int jugador = rematar[i];
            if ( jugador != 0 )
            {
                if ( equipo[jugador].distancia( new Posicion( 0, 52.50 ) ) < 40 )
                {
                    alto = equipo[jugador].distancia( new Posicion( 0, 52.50 ) ) > 25;
                    comandos.add( new ComandoGolpearBalon( jugador, new Posicion( 0, 52.50 ), 1, alto ) );
                }
                else
                {
                    int mascercano = 0;
                    double distancia = 1000.0;
                    for ( int j = 1; j < 11; j++ )
                    {
                        if ( j != jugador )
                        {
                            if ( equipo[j].getY() > equipo[jugador].getY() + 10 )
                            {
                                if ( equipo[jugador].distancia( equipo[j] ) < distancia )
                                {
                                    distancia = equipo[jugador].distancia( equipo[j] );
                                    mascercano = j;
                                }
                            }
                        }
                    }

                    if ( mascercano != 0 )
                    {
                        alto = equipo[jugador].distancia( equipo[mascercano] ) < 25;
                        comandos.add( new ComandoGolpearBalon( jugador, equipo[mascercano], 1, alto ) );
                    }
                    else
                    {
                        comandos.add( new ComandoGolpearBalon( jugador,new Posicion (equipo[jugador].getX(),52.50),0,false ) );
                    }
                }
            }
        }
        balonAnterior = balon;

        return comandos;
    }
}